<?php

declare(strict_types=1);

namespace IdaasClient\Middleware;

use App\Utils\IdaasUtil;
use App\Utils\UserTokenUtil;
use Hyperf\Context\Context;
use Hyperf\Grpc\StatusCode;
use Hyperf\GrpcServer\Exception\GrpcException;
use Hyperf\HttpServer\Router\Dispatched;
use Hyperf\Utils\ApplicationContext;
use Hyperf\Utils\Network;
use Hyperfx\Framework\Exception\AppException;
use Hyperfx\Framework\Logger\Logx;
use IdaasClient\Constants\IdaasConst;
use IdaasClient\Utils\IdaasClientUtil;
use Psr\Container\ContainerInterface;
use Psr\Http\Message\ResponseInterface;
use Psr\Http\Server\MiddlewareInterface;
use Psr\Http\Message\ServerRequestInterface;
use Psr\Http\Server\RequestHandlerInterface;

class AuthMiddleware implements MiddlewareInterface
{
    use BaseMiddleware;
    // 是否开启
    protected ?bool $enable = true;

    // 使用哪个配置文件实例
    protected ?string $instance;
    // 使用哪个项目
    protected ?string $project;
    // 需要的资源
    protected ?array $resources;
    // 是否验证权限
    protected ?bool $isCheckPermission = true;
    // 允许的访问用户类型
    protected ?array $allowUserTypes = [];

    // 项目ID
    protected ?string $projectId;
    // 固定的projectid
    protected ?string $xProjectId = '';
    // 配置文件
    private ?array $config;
    // 池
    private ?string $poolId;
    // 不需要鉴权的角色
    // private array $noCheckRoleIds = [];


    public function __construct(protected ContainerInterface $container)
    {
        $this->config = config(sprintf('idaas.%s', $this->instance));
        $this->poolId = $this->config['pool_id'];
    }

    public function process(ServerRequestInterface $request, RequestHandlerInterface $handler): ResponseInterface
    {
        if (!$this->enable) {
            return $handler->handle($request);
        }

        // 获取当前登录的用户信息
        $userInfo = $this->getUserInfo($request);
        // 检查用户类型
        $this->checkUserType($userInfo);

        // 是否验证权限
        if ($this->isCheckPermission) {

            $this->projectId = $this->getProjectId($request);

            // 获取当前路由权限值
            $permission = $this->getRoutePermission($request);
            // 获取这个用户的权限
            $userPermissions = $this->getUserPermissions($userInfo['user_id'], $userInfo['session_id']);

            Logx::get()->debug('获取到的权限信息', [
                'project_id' => $this->projectId,
                'current_permission' => $permission,
                'getUserPermissions' => $userPermissions
            ]);

            // 路由信息
            $routeResourceInfo = $this->getRouteInfo($request, $userInfo);

            // 对比权限
            if (!$this->diffPermission($userPermissions, $routeResourceInfo, $permission)) {
                Logx::get()->error('您没有此权限', [
                    'x_group' => 'checkPermission',
                    'userPermissions' => $userPermissions,
                    'routeInfo' => $routeResourceInfo,
                ]);
                throw new GrpcException('您没有此权限', StatusCode::PERMISSION_DENIED);
            }

            // 检查资源
            $this->checkResource(
                partnerId: $routeResourceInfo['partner_id'] ?? 0,
                siteId: $routeResourceInfo['site_id'] ?? '',
                namespace: $routeResourceInfo['namespace'] ?? ''
            );

            // 解析部门ID
            $this->parseDeptIds($userPermissions, $permission, $routeResourceInfo);

            if (method_exists($this, 'handleBefore')) {
                $this->handleBefore($request, $routeResourceInfo);
            }
        }
        return $handler->handle($request);
    }
}